#include "widget.h"
// 包含UI界面自动生成的头文件（由Qt Designer生成）
#include "ui_widget.h"
// 包含Qt消息框类（用于弹出错误提示等）
#include <QMessageBox>
// 包含Qt列表部件类（用于显示日志信息）
#include <QListWidget>
// 包含Qt字符串类（处理文本数据）
#include <QString>
// 注意：原代码缺少QTcpServer和QTcpSocket的头文件，实际使用需补充：
// #include <QTcpServer>  // TCP服务器核心类
// #include <QTcpSocket>  // 处理TCP连接的套接字类
// #include <QHostAddress> // 处理IP地址的类


// Widget类构造函数：初始化窗口和服务器
Widget::Widget(QWidget *parent)
    : QWidget(parent)  // 调用父类QWidget的构造函数
    , ui(new Ui::Widget)  // 初始化UI对象（加载界面布局）
{
    // 初始化UI界面（根据Qt Designer设计的界面生成控件）
    ui->setupUi(this);

    // 1. 设置窗口标题为"服务器"
    this->setWindowTitle("服务器");

    // 2. 创建TCP服务器对象：
    //    以当前Widget为父对象，确保服务器对象生命周期与窗口一致（窗口销毁时自动释放）
    tcpServer = new QTcpServer(this);

    // 3. 关联"新连接"信号与处理函数：
    //    当有客户端尝试连接服务器时，QTcpServer会触发newConnection信号
    //    此处将信号绑定到processConnection槽函数，用于处理新连接
    connect(tcpServer, &QTcpServer::newConnection, this, &Widget::processConnection);

    // 4. 绑定IP地址并监听端口：
    //    QHostAddress::Any表示监听本机所有可用网络接口（如以太网、WiFi等）
    //    端口号8080（可根据需求修改，需确保未被占用）
    bool ret = tcpServer->listen(QHostAddress::Any, 8080);
    // 如果监听失败（如端口被占用）
    if(!ret)
    {
        // 弹出错误提示框，显示失败原因（tcpServer->errorString()返回具体错误信息）
        QMessageBox::critical(this, "服务器启动失败！", tcpServer->errorString());
        // 退出程序（1表示异常退出）
        exit(1);
    }
}

// Widget类析构函数：释放资源
Widget::~Widget()
{
    // 释放UI对象占用的内存
    delete ui;
}

// 处理新客户端连接的槽函数
void Widget::processConnection()
{
    // 1. 获取客户端连接的套接字对象：
    //    nextPendingConnection()返回一个新的QTcpSocket对象，用于与当前客户端通信
    //    每个客户端连接对应一个独立的QTcpSocket，需单独管理
    QTcpSocket* clientSocket = tcpServer->nextPendingConnection();

    // 记录客户端连接成功的日志：
    // peerAddress().toString()：获取客户端的IP地址并转为字符串
    // peerPort()：获取客户端的端口号（转为字符串）
    QString log = "[" + clientSocket->peerAddress().toString() + ":" +
                  QString::number(clientSocket->peerPort()) + "], 客户端连接成功";
    // 将日志添加到界面的列表部件（ui->listWidget）中显示
    ui->listWidget->addItem(log);

    // 2. 处理客户端发送的数据：
    //    当客户端发送数据时，QTcpSocket会触发readyRead信号
    //    绑定信号到匿名lambda函数，读取数据并回复
    connect(clientSocket, &QTcpSocket::readyRead, this, [=](){
        // 读取客户端发送的所有数据：
        // readAll()返回QByteArray（字节数组），转为QString便于处理文本
        QString request = clientSocket->readAll();
        // 调用process函数处理请求（此处简单返回原内容，实际可扩展业务逻辑）
        const QString& response = process(request);
        // 将处理结果发送回客户端：
        // toUtf8()将QString转为UTF-8编码的字节数组（网络传输需用字节流）
        clientSocket->write(response.toUtf8());

        // 记录请求和响应的日志
        QString log = "[" + clientSocket->peerAddress().toString() + ":" + QString::number(clientSocket->peerPort())
                      + " req : "+ request + " resp: " + response;
        ui->listWidget->addItem(log);
    });

    // 3. 处理客户端断开连接的情况：
    //    当客户端断开连接时，QTcpSocket会触发disconnected信号
    connect(clientSocket, &QTcpSocket::disconnected, this, [=](){
        // 记录客户端断开连接的日志
        QString log = "[" + clientSocket->peerAddress().toString() + ":" +
                      QString::number(clientSocket->peerPort()) + "], 客户端断开连接";
        ui->listWidget->addItem(log);

        // 释放客户端套接字资源：
        // 不直接使用delete，因为若槽函数中存在return或异常，可能导致未释放
        // deleteLater()：告诉Qt在当前事件循环结束后再销毁对象，确保资源安全释放
        clientSocket->deleteLater();
    });
}

// 处理客户端请求的函数（业务逻辑层）
// 此处为示例：直接返回客户端发送的内容（回声功能）
// 实际应用中可根据需求修改（如解析指令、查询数据库等）
QString Widget::process(const QString& request)
{
    return request;
}
